package cz.semjobKB.virtuoso.utils;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import org.springframework.stereotype.Component;

@Component
public class VirtuosoUtils {
	
	private static final String SEMJOB_PREFIX_URI = "http://datlowe.org/semjobKB/ontologies/domain/document#";
	private static final String DOCUMENT_PREFIX_URI = "http://datlowe.org/semjobKB/data/document/document#";
	private static final String TERM_BASE_URI = "http://datlowe.org/semjobKB/data/document/term#";
	private static final String PREDICAT_BASE_URI = "http://datlowe.org/semjobKB/data/document/predicate#";
	private static final String TERMINOLOGY_BASE_URI = "http://datlowe.org/semjobKB/data/document/Terminology#";
		
	private Map<String, String> knownGraphsUris = new HashMap<String, String>();
	private Map<String, String> ontologyNodes = new HashMap<String, String>();
	private final HashMap<String, String> SPARQL_ESCAPE_SEARCH_REPLACEMENTS = new HashMap<String, String>();
	
	public VirtuosoUtils() {		
		
		knownGraphsUris.put("ontology", SEMJOB_PREFIX_URI);
		knownGraphsUris.put("document", DOCUMENT_PREFIX_URI);
		knownGraphsUris.put("terms", TERM_BASE_URI);
		knownGraphsUris.put("predicates", PREDICAT_BASE_URI);
		knownGraphsUris.put("terminology", TERMINOLOGY_BASE_URI);
		
		ontologyNodes.put("Document", SEMJOB_PREFIX_URI + "Document");
		ontologyNodes.put("hasName", SEMJOB_PREFIX_URI + "hasName");
		ontologyNodes.put("hasLocation", SEMJOB_PREFIX_URI + "hasLocation");
		
		ontologyNodes.put("Term", SEMJOB_PREFIX_URI + "Term");
		ontologyNodes.put("Predicate", SEMJOB_PREFIX_URI + "Predicate");
		ontologyNodes.put("TerminologyItem", SEMJOB_PREFIX_URI + "TerminologyItem");
		
		ontologyNodes.put("language", SEMJOB_PREFIX_URI + "language");
		ontologyNodes.put("hasLemma", SEMJOB_PREFIX_URI + "hasLemma");
		ontologyNodes.put("has", SEMJOB_PREFIX_URI + "has");
		ontologyNodes.put("hasStringRepresentation", SEMJOB_PREFIX_URI + "hasStringRepresentation");		
		
		ontologyNodes.put("hasFrequency", SEMJOB_PREFIX_URI + "hasFrequency");
		ontologyNodes.put("hasOverallFrequency", SEMJOB_PREFIX_URI + "hasOverallFrequency");
		ontologyNodes.put("hasTotalCount", SEMJOB_PREFIX_URI + "hasTotalCount");
		
		ontologyNodes.put("hasTermCount", SEMJOB_PREFIX_URI + "hasTotalTermCount");
		ontologyNodes.put("hasPredicateCount", SEMJOB_PREFIX_URI + "hasTotalPredCount");
		ontologyNodes.put("hasTerminologyCount", SEMJOB_PREFIX_URI + "hasTerminologyCount");
		ontologyNodes.put("hasSentenceCount", SEMJOB_PREFIX_URI + "hasSentenceCount");
		
		ontologyNodes.put("a", "http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
		
		SPARQL_ESCAPE_SEARCH_REPLACEMENTS.put("\t", "\\t");
		SPARQL_ESCAPE_SEARCH_REPLACEMENTS.put("\n", "\\n");
		SPARQL_ESCAPE_SEARCH_REPLACEMENTS.put("\r", "\\r");
		SPARQL_ESCAPE_SEARCH_REPLACEMENTS.put("\b", "\\b");
		SPARQL_ESCAPE_SEARCH_REPLACEMENTS.put("\f", "\\f");
		SPARQL_ESCAPE_SEARCH_REPLACEMENTS.put("\"", "\\\"");
		SPARQL_ESCAPE_SEARCH_REPLACEMENTS.put("'", "\\'");
		SPARQL_ESCAPE_SEARCH_REPLACEMENTS.put("`", "_");
		SPARQL_ESCAPE_SEARCH_REPLACEMENTS.put("%", "%25");
		SPARQL_ESCAPE_SEARCH_REPLACEMENTS.put("\\", "\\\\");
		
	}
	
	public Map<String, String> getKnownGraphsUris() {
		return knownGraphsUris;
	}
	
	public Map<String, String> getOntologyNodes() {
		return ontologyNodes;
	}
	
	public String escape(String string) {
		
		StringBuffer bufOutput = new StringBuffer(string);
		for (int i = 0; i < bufOutput.length(); i++) {
			String replacement = SPARQL_ESCAPE_SEARCH_REPLACEMENTS.get("" + bufOutput.charAt(i));
			if(replacement!=null) {
				bufOutput.deleteCharAt(i);
				bufOutput.insert(i, replacement);
				// advance past the replacement
				i += (replacement.length() - 1);
			}
		}
		return bufOutput.toString();
	}
	
	public <K, V extends Comparable<V>> Map<K, V> sortByValues(final Map<K, V> map) {
	    Comparator<K> valueComparator =  new Comparator<K>() {
	        public int compare(K k1, K k2) {
	            int compare = map.get(k2).compareTo(map.get(k1));
	            if (compare == 0) return 1;
	            else return compare;
	        }
	    };
	    Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator);
	    sortedByValues.putAll(map);
	    return sortedByValues;
	}
}
